package com.example.zxx.springboot3.util;

import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * IIfUtil:if工具类,参考JDK8 Optional类
 *
 * @author zhangxiaoxiang
 * @date 2022年2月1日
 */

public interface IfUtil {

    IfUtil BUILD = new IfUtil() {
    };


    default <T, R, E extends RuntimeException> R ifThrowable(T t, Predicate<T> rule, Function<T, R> function, Supplier<? extends E> elseThrow) throws E {
        if (rule.test(t)) {
            return function.apply(t);
        }
        throw elseThrow.get();
    }

    /**
     * 满足条件,执行if
     *
     * @param rule  判断规则
     * @param param 请求参数
     * @param then  满足条件执行
     * @param <P>   请求参数
     */
    default <P> void ifThenVoid(boolean rule, P param, Consumer<P> then) {
        if (rule) {
            then.accept(param);
        }
    }

    /**
     * [带返回值]判断是否满足条件,满足就执行逻辑并返回,否则返回null </p>
     * 处理 if(){赋值业务逻辑} 类型逻辑
     *
     * @param param 请求参数
     * @param rule  判断规则
     * @param then  业务逻辑
     * @param <P>   请求参数类型
     * @param <R>   返回值类型
     * @return 返回值
     */
    default <P, R> R ifThenValue(P param, Predicate<P> rule, Function<P, R> then) {
        return rule.test(param) ? then.apply(param) : null;
    }

    /**
     * 如果存在值，则使用该值执行给定的操作，否则执行给定的基于空的操作
     *
     * @param param       请求参数
     * @param rule        判断规则
     * @param action      操作
     * @param emptyAction 为空的操作
     * @param <P>         请求参数类型
     */
    default <P> void ifPresentOrElse(P param, Predicate<P> rule, Consumer<P> action, Runnable emptyAction) {
        if (rule.test(param)) {
            action.accept(param);
        } else {
            emptyAction.run();
        }
    }

    /**
     * [不带返回值]满足条件执行逻辑
     *
     * @param param 请求参数
     * @param rule  判断规则
     * @param then  满足规则执行逻辑
     * @param <P>   参数类型
     */
    default <P> void ifThenVoid(P param, Predicate<P> rule, Consumer<P> then) {
        if (rule.test(param)) {
            then.accept(param);
        }
    }


    /**
     * [带返回值]满足条件执行逻辑获取值,不满足执行另一个逻辑获取值 </p>
     * 处理典型的if else类型 </p>
     * 三目运算return rule ? then.get() : orElse.get();
     *
     * @param rule   判断规则
     * @param then   满足条件执行逻辑,返回值
     * @param orElse 不满足执行另一个逻辑,返回值
     * @param <R>    返回值类型
     * @return 返回值
     */
    default <R> R ifOrElseGet(boolean rule, Supplier<R> then, Supplier<R> orElse) {
        return rule ? then.get() : orElse.get();
    }

    /**
     * [带返回值]满足条件执行逻辑获取值,不满足执行另一个逻辑获取值 </p>
     *
     * @param param  请求参数
     * @param rule   判断规则
     * @param then   满足if规则执行逻辑返回值
     * @param orElse orElse执行逻辑返回值
     * @param <P>    请求参数类型
     * @param <R>    返回参数类型
     * @return 返回值
     */
    default <P, R> R ifOrElseGet(P param, Predicate<P> rule, Supplier<R> then, Supplier<R> orElse) {
        return rule.test(param) ? then.get() : orElse.get();
    }

    /**
     * 满足条件执行逻辑,不满足直接抛异常
     *
     * @param param     请求参数
     * @param rule      if规则
     * @param then      执行if规则逻辑
     * @param elseThrow 不满足抛异常
     * @param <E>       异常
     * @param <P>       请求参数
     * @param <R>       返回参数
     * @return 返回值
     * @throws E 异常
     */
    default <E extends Throwable, P, R> R ifOrElseThrow(P param, Predicate<P> rule, Supplier<R> then, Supplier<? extends E> elseThrow) throws E {
        if (rule.test(param)) {
            return then.get();
        }
        throw elseThrow.get();
    }

    /**
     * [不带返回值]请求参数满足条件执行逻辑,不满足执行另一个逻辑
     *
     * @param param  请求参数
     * @param rule   判断规则
     * @param then   满足条件执行逻辑,
     * @param orElse 不满足执行另一个逻辑
     * @param <T>    请求参数类型
     */
    default <T> void ifOrElseVoid(T param, Predicate<T> rule, Consumer<T> then, Consumer<T> orElse) {
        if (rule.test(param)) {
            then.accept(param);
        } else {
            orElse.accept(param);
        }
    }

    /**
     * 嵌套if,返回对应的匹配值,类比Optional的.filter()链式调用
     *
     * @param param       请求参数
     * @param map         map请求参数
     * @param defaultThen 未匹配默认返回值
     * @param <T>         请求参数类型
     * @param <R>         返回值类型
     * @return 返回值
     */
    default <T, R> R nestedIfValue(T param, Map<Predicate<T>, Function<T, R>> map, Function<T, R> defaultThen) {
        for (Map.Entry<Predicate<T>, Function<T, R>> entry : map.entrySet()) {
            return ifThenValue(param, t -> entry.getKey().test(param), t -> null);
        }
        // return Objects.nonNull(defaultThen) ? defaultThen.apply(param) : null;
        return ifOrElseGet(Objects.nonNull(defaultThen), () -> defaultThen.apply(param), () -> null);

    }


    /**
     * 嵌套if型执行逻辑,无返回值,类比Optional的.filter()链式调用
     *
     * @param param 请求参数
     * @param map   嵌套if转成的map
     * @param <P>   请求参数类型
     */
    default <P> void nestedIfVoid(P param, Map<Predicate<P>, Consumer<P>> map) {
        for (Map.Entry<Predicate<P>, Consumer<P>> entry : map.entrySet()) {
            if (entry.getKey().test(param)) {
                entry.getValue().accept(param);
                return;
            }
        }
    }

    /**
     * 嵌套if型执行逻辑,无返回值,默认匹配执行
     *
     * @param param       请求参数
     * @param map         嵌套if转成的map
     * @param defaultThen 默认逻辑
     * @param <P>         请求参数类型
     */
    default <P> void nestedIfVoid(P param, Map<Predicate<P>, Consumer<P>> map, Consumer<P> defaultThen) {
        for (Map.Entry<Predicate<P>, Consumer<P>> entry : map.entrySet()) {
            if (entry.getKey().test(param)) {
                entry.getValue().accept(param);
                return;
            }
        }
        defaultThen.accept(param);
    }

    /**
     * 满足条件就直接抛异常
     *
     * @param rule      规则
     * @param elseThrow 不满足条件抛异常
     * @param <E>       异常
     * @throws E 抛异常
     */
    default <E extends Throwable> void ifThrow(boolean rule, Supplier<? extends E> elseThrow) throws E {
        if (rule) {
            throw elseThrow.get();
        }
    }

}